package com.wyt.cloud.utils.query.duty.handler;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.wyt.cloud.utils.TransferEnum;
import com.wyt.cloud.utils.designpatterns.dutychain.IHandler;
import com.wyt.cloud.utils.query.ClazzFieldsUtil;
import com.wyt.cloud.utils.query.FilterMatchRuleEnum;
import com.wyt.cloud.utils.query.anno.FilterParam;
import com.wyt.cloud.utils.query.duty.QueryTask;
import com.wyt.cloud.utils.query.reqvo.FilterFieldEntity;
import com.wyt.cloud.utils.query.strategy.QueryMatchStrategy;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Order(2)
@Component
public class BuildFiltersHandler<S, T> implements IHandler<QueryTask<S, T>> {

    @Autowired
    private List<QueryMatchStrategy> queryMatchStrategies;


    @Override
    public void execute(QueryTask<S, T> task) {
        buildParams(task.getWrapper(), new BeanWrapperImpl(task.getEntity()),task.getTClass());
    }

    /**
     * @param wrapper
     * @param beanWrapper
     * @param tClass
     */
    private void buildParams(QueryWrapper<T> wrapper, BeanWrapperImpl beanWrapper, Class<T> tClass) {
        Field[] declaredFields = beanWrapper.getRootClass().getDeclaredFields();
        List<Field> targetFields = ClazzFieldsUtil.getAllFields(tClass);
        Map<String, Field> targetFieldTypeMap = targetFields.stream().collect(Collectors.toMap(Field::getName, Function.identity()));
        for (Field field : declaredFields) {
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            if (QueryTask.sortFields.equals(field.getName())) {
                continue;
            }
            Field targetField = targetFieldTypeMap.get(field.getName());
            FilterParam annotation = field.getAnnotation(FilterParam.class);
            if(targetField==null){
                targetField = targetFieldTypeMap.get(annotation.matchField());
            }
            buildWrapperByField(wrapper, field, annotation, beanWrapper.getPropertyValue(field.getName()), targetField);
        }
    }

    /**
     * 根据当前字段和注解情况构建wrapper条件
     *
     * @param wrapper
     * @param field
     * @param filterParam
     * @param value
     * @param targetField
     */
    private void buildWrapperByField(QueryWrapper<T> wrapper, Field field, FilterParam filterParam, Object value, Field targetField) {
        FilterFieldEntity filterFieldEntity = buildQueryParamEntity(filterParam, value);
        if (!filterFieldEntity.isNeedMatch()) {
            return;
        }
        if (!QueryTask.nullAboutList.contains(filterFieldEntity.getMatchRule())) {
            if (Objects.isNull(value)) {
                return;
            }
            if (value instanceof String && StringUtils.isBlank(String.valueOf(value))) {
                return;
            }
            if (value instanceof Collection && CollectionUtils.isEmpty((Collection<?>) value)) {
                return;
            }
        }

        try {
            for (QueryMatchStrategy matchStrategy : queryMatchStrategies) {
                if (matchStrategy.when(filterFieldEntity.getMatchRule())) {
                    if (value instanceof TransferEnum && (targetField.getType().equals(Integer.class) || targetField.getType().equals(int.class))) {
                        matchStrategy.then(wrapper, field, ((TransferEnum<?>) value).getCode(), targetField);
                    } else if (value instanceof Long && targetField.getType().equals(Date.class)) {
                        matchStrategy.then(wrapper, field, new Date((Long) value), targetField);
                    } else {
                        matchStrategy.then(wrapper, field, value, targetField);
                    }
                }
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据QueryParam的入参情况构建QueryParamEntity对象
     *
     * @param filterParam
     * @param value
     * @return
     */
    private static FilterFieldEntity buildQueryParamEntity(FilterParam filterParam, Object value) {
        FilterFieldEntity filterFieldEntity = new FilterFieldEntity();
        if (filterParam == null) {
            filterFieldEntity.setNeedMatch(true);
            if (value instanceof Collection) {
                filterFieldEntity.setMatchRule(FilterMatchRuleEnum.IN);
            } else {
                filterFieldEntity.setMatchRule(FilterMatchRuleEnum.EQ);
            }
            return filterFieldEntity;
        }

        filterFieldEntity.setMatchField(filterParam.matchField());
        filterFieldEntity.setNeedMatch(filterParam.needMatch());
        //matchRule默认为EQ
        if (FilterMatchRuleEnum.EQ.equals(filterParam.matchRule())) {
            if (value instanceof Collection) {
                filterFieldEntity.setMatchRule(FilterMatchRuleEnum.IN);
            } else {
                filterFieldEntity.setMatchRule(FilterMatchRuleEnum.EQ);
            }
        } else {
            filterFieldEntity.setMatchRule(filterParam.matchRule());
        }
        return filterFieldEntity;
    }

}
